import { Application, ImageSource } from 'pixi.js';
import { Scene_Base } from '@/scenes/Scene_Base.js';
import { ImageManager } from '@/managers/ImageManager.js';
import { AudioManager } from '@/managers/AudioManager.js';
import { DataManager } from '@/managers/DataManager.js';

import { TouchInput } from '@/core/TouchInput.js';
import { Input } from '@/core/Input.js';

import {TexturePool} from '@/utils/TexturePool.js';
import { SpritePool } from '@/utils/SpritePool.js';
const app=new Application();
window.app=app;
export class SceneManager {

    static previousScene=null;
    /**
     * @type {Scene_Base}
     */
    static scene = null;
    /**
     * @type {Scene_Base}
     */
    static nextScene = null;
    /**
     * @type {Scene_Base[]}
     */
    static stack = [];

    /**
     * @type {boolean}
     */
    static sceneStarted = false;

    static backgroundSource=null;

    static run(sceneClass) {
        this.init().then(async ()=>{
            this.goto(sceneClass);
            app.ticker.add(this.update);
            document.fonts.ready.then(()=>{
                window.fontloaded=true;
            })
        });
    }

    static async init() {
        await app.init({sharedTicker:true,resizeTo:window,background:'#000'});
        document.body.appendChild(app.canvas);
        AudioManager.init();
        ImageManager.preloadSystem();
        this.initInput();
    }

    static initInput(){
        app.stage.eventMode='static';
        Input.initialize();
        TouchInput.initialize(app);
    }

    static update=(ticker)=>{
        Input.update();
        TouchInput.update();
        this.updateMain();
    }

    static terminate() {
        this.scene?.terminate();
        if(app.renderer){
            app.ticker.remove(this.update);
            app.destroy(false,true);
        }
        SpritePool.close();
        TexturePool.close();
        ImageManager.destroy();
        AudioManager.destroy();
        DataManager.destroy();
    }

    static updateMain() {
        this.tryChangeScene();
        this.updateScene();
    }


    static tryChangeScene() {
        if (this.nextScene && !this.scene?.isBusy()) {
            if (this.scene) {
                app.stage.removeChild(this.scene);
                this.scene.terminate();
                this.previousScene=this.scene.constructor;
            }
            this.scene = this.nextScene;
            if (this.scene) {
                this.scene.create();
                this.nextScene = null;
                this.sceneStarted = false;
            }
        }
    }

    static updateScene() {
        if (this.scene) {
            if (!this.sceneStarted && this.scene.isReady()) {
                this.scene.start();
                this.sceneStarted = true;
                app.stage.addChild(this.scene);
            }
            if (this.sceneStarted) {
                this.scene.update();
            }
        }
    }

    static goto(sceneClass) {
        if (sceneClass) {
            this.nextScene = new sceneClass();
        }
        this.scene?.stop();
    }

    static push(sceneClass) {
        this.stack.push(this.scene.constructor);
        this.goto(sceneClass);
    }

    static pop() {
        if (this.stack.length > 0) {
            this.goto(this.stack.pop());
        }
    }

    static isNextScene(sceneClass) {
        return this.nextScene && this.nextScene.constructor == sceneClass;
    }

    static isPreviousScene(sceneClass){
        return this.previousScene&&this.previousScene==sceneClass;
    }

    static async snapForBackground(){
        if(this.scene){
            let resource= await app.renderer.extract.image(this.scene);
            if(this.backgroundSource){
                this.backgroundSource.destroy();
                this.backgroundSource=null;
            }
            this.backgroundSource=new ImageSource({resource, scaleMode: 'nearest'});
        }
    }
    static backgroundBitmap() {
        return this.backgroundSource;
    }

    static isSceneChanging(){
        return !!this.nextScene;
    }

    static stop(){
        app.ticker.stop();
    }

    static resume(){
        app.ticker.start();
    }

    static clearStack() {
        this.stack = [];
    }
}